home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n02 / uxdriver.exe / CONS.C next >
Encoding:
C/C++ Source or Header  |  1991-11-19  |  19.9 KB  |  785 lines

  1. /* cons.c
  2.  * Copyright (c) 1989, 1990, 1991 William Jolitz. All rights reserved.
  3.  * Written by William Jolitz 9/89
  4.  *
  5.  * Redistribution and use in source and binary forms are freely permitted
  6.  * provided that the above copyright notice and attribution and date of work
  7.  * and this paragraph are duplicated in all such forms.
  8.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  9.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  10.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  11.  *
  12.  * Added support for ibmpc term type and improved keyboard support. -Don Ahn
  13.  *
  14.  */
  15.  
  16. /*
  17.  * code to work keyboard & display for console
  18.  */
  19. #include "param.h"
  20. #include "conf.h"
  21. #include "ioctl.h"
  22. #include "user.h"
  23. #include "proc.h"
  24. #include "tty.h"
  25. #include "uio.h"
  26. #include "i386/isa/isa_device.h"
  27. #include "callout.h"
  28. #include "systm.h"
  29. #include "kernel.h"
  30. #include "syslog.h"
  31. #include "malloc.h"
  32. #include "i386/isa/icu.h"
  33. #include "i386/isa/isa.h"
  34.  
  35. #define    KBSTAT        0x64    /* kbd status port */
  36. #define    KBSTAT_RDY    0x02    /* kbd data ready */
  37. #define    KBSTAT_CMDRDY    0x02    /* kbd ready for command */
  38. #define    WAITKBDCMD    while (inb(KBSTAT) & KBSTAT_CMDRDY)
  39. #define    KBDATA        0x60    /* kbd data port */
  40. #define    KEY_DEL    83
  41. #define    KEY_BREAK    0x80
  42. #define    KEY_CODE    0x7f
  43. #define    KEY_NOKEY    0x100
  44.  
  45. struct    tty cons;
  46.  
  47. int cnprobe(), cnattach();
  48.  
  49. struct    isa_driver cndriver = {
  50.     cnprobe, cnattach, "cn",
  51. };
  52.  
  53.  
  54. #define    COL        80
  55. #define    ROW        25
  56. #define    CHR        2
  57. #define MONO_BASE    0x3B4
  58. #define MONO_BUF    0xB0000
  59. #define CGA_BASE    0x3D4
  60. #define CGA_BUF        0xB8000
  61. #define IOPHYSMEM    0xA0000
  62.  
  63. union    crtbuf {
  64.     struct crtbyte {
  65.         u_char    chr;
  66.         union    att {
  67.             u_char    attr; /* attribute : color, blink, bold, ... */
  68.             struct crtattbit {
  69.                 u_char    fg:4;    /* foreground */
  70.                 u_char    bg:4;    /* background */
  71.             } c_attrbit;
  72.         } c_att;
  73.     } c_byte;
  74. #define    c_chr    c_byte.chr
  75. #define    c_attr    c_byte.c_att.attr
  76. #define    c_fgat    c_byte.c_att.c_attrbit.fg
  77. #define    c_bgat    c_byte.c_att.c_attrbit.bg
  78.     u_short    c_wd;
  79. } *Crtat = (union crtbuf *)MONO_BUF;
  80.  
  81. struct crtscreen {
  82.     union crtbuf s_buf[ROW*COL];
  83.     u_short    s_cursor;
  84. /* these are wrong: bgat is only a fill attribute, curat is the
  85. attribute written with the text, dfltat is the previous attribute
  86. prior to a standout mode, and there is no stand out mode attrib.*/
  87.     u_char    s_bgat; /* background or fill attribute */ 
  88.     u_char    s_curat; /* foreground or current attribute */ 
  89.     u_char    s_dfltat; /* default attribute */ 
  90.     struct    crtscreen *s_back;    /* previous screen */
  91.     struct    crtscreen *s_next;    /* next screen */
  92. } *dispsp,    /* this is the currently displaying screen */
  93. toplvl,        /* this is the top level open process screen */
  94. *conssp,    /* this is the console of the moment */
  95. sysscreen;     /* this is the system's screen (for system error messages)*/
  96.  
  97. static unsigned int addr_6845 = MONO_BASE;
  98.  
  99. int    cnstart(), cnparam(), ttrstrt();
  100. char    partab[];
  101.  
  102. cnprobe(dev)
  103. struct isa_device *dev;
  104. {
  105.     u_char c;
  106.     int again = 0;
  107.  
  108.     /* Enable interrupts and keyboard controller */
  109.     WAITKBDCMD; outb(KBSTAT,0x60);
  110.     WAITKBDCMD; outb(KBDATA,0x4D);
  111.  
  112.     /* Start keyboard stuff RESET */
  113.     WAITKBDCMD; outb(KBDATA,0xFF);    /* RESET */
  114.  
  115.     while((c=inb(KBDATA))!=0xFA) {
  116.         if ((c == 0xFE) ||  (c == 0xFF)) {
  117.             WAITKBDCMD;
  118.             outb(KBDATA,0xFF);    /* RESET */
  119.             again = 1;
  120.         }
  121.     }
  122.  
  123.     /* pick up keyboard reset return code */
  124.     while((c=inb(KBDATA))!=0xAA)nulldev();
  125.     return 1;
  126. }
  127.  
  128. cnattach(dev)
  129. struct isa_device *dev;
  130. {
  131.     union crtbuf *cp = Crtat + (CGA_BUF-MONO_BUF)/CHR;
  132.     u_short was;
  133.  
  134.     /* Crtat initialized to point to MONO buffer   */
  135.     /* if not present change to CGA_BUF offset     */
  136.     /* ONLY ADD the difference since locore.s adds */
  137.     /* in the remapped offset at the right time    */
  138.  
  139.     was = Crtat->c_wd;
  140.     Crtat->c_wd = 0xA55A;
  141.     if (Crtat->c_wd != 0xA55A)
  142.         printf("<mono>");
  143.     else    printf("<color>");
  144.     Crtat->c_wd = was;
  145.     update_cursor(dispsp);
  146. }
  147. static char openf;
  148.  
  149. /*ARGSUSED*/
  150. cnopen(dev, flag)
  151.     dev_t dev;
  152. {
  153.     register struct tty *tp;
  154.  
  155.     tp = &cons;
  156.     tp->t_oproc = cnstart;
  157.     tp->t_param = cnparam;
  158.     tp->t_dev = dev;
  159.  
  160.     /* if no top level screen allocated, allocate */
  161.     if (openf++ == 0) {
  162.         initscrn(&toplvl);
  163.         conssp = &toplvl;
  164.         gotoscrn(conssp);
  165.     }
  166.  
  167.     if ((tp->t_state & TS_ISOPEN) == 0) {
  168.         tp->t_state |= TS_WOPEN;
  169.         ttychars(tp);
  170.         tp->t_iflag = TTYDEF_IFLAG;
  171.         tp->t_oflag = TTYDEF_OFLAG;
  172.         tp->t_cflag = TTYDEF_CFLAG;
  173.         tp->t_lflag = TTYDEF_LFLAG;
  174.         tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  175.         cnparam(tp, &tp->t_termios);
  176.         ttsetwater(tp);
  177.     } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
  178.         return (EBUSY);
  179.     tp->t_state |= TS_CARR_ON;
  180.     return ((*linesw[tp->t_line].l_open)(dev, tp));
  181. }
  182.  
  183. cnclose(dev, flag)
  184.     dev_t dev;
  185. {
  186.     (*linesw[cons.t_line].l_close)(&cons);
  187.     ttyclose(&cons);
  188.     return(0);
  189. }
  190.  
  191. /*ARGSUSED*/
  192. cnread(dev, uio, flag)
  193.     dev_t dev;
  194.     struct uio *uio;
  195. {
  196.     return ((*linesw[cons.t_line].l_read)(&cons, uio, flag));
  197. }
  198.  
  199. /*ARGSUSED*/
  200. cnwrite(dev, uio, flag)
  201.     dev_t dev;
  202.     struct uio *uio;
  203. {
  204.     return ((*linesw[cons.t_line].l_write)(&cons, uio, flag));
  205. }
  206.  
  207. /*
  208.  * Got a console receive interrupt -
  209.  * the console processor wants to give us a character.
  210.  * Catch the character, and see who it goes to.
  211.  */
  212. cnrint(dev, irq, cpl)
  213.     dev_t dev;
  214. {
  215.     int c;
  216.  
  217.     c = sgetc();
  218.     if(dispsp != conssp) gotoscrn(conssp);
  219.     if (c == KBD_NOKEY) return;
  220.     (*linesw[cons.t_line].l_rint)(c&0xff, &cons);
  221. }
  222.  
  223. cnioctl(dev, cmd, data, flag)
  224.     dev_t dev;
  225.     caddr_t data;
  226. {
  227.     register struct tty *tp = &cons;
  228.     register error;
  229.  
  230.     error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
  231.     if (error >= 0)
  232.         return (error);
  233.     error = ttioctl(tp, cmd, data, flag);
  234.     if (error >= 0)
  235.         return (error);
  236.     return (ENOTTY);
  237. }
  238.  
  239. int    consintr = 1;
  240. /*
  241.  * Got a console transmission interrupt -
  242.  * the console processor wants another character.
  243.  */
  244. cnxint(dev)
  245.     dev_t dev;
  246. {
  247.     register struct tty *tp;
  248.     register int unit;
  249.  
  250.     if (!consintr)
  251.         return;
  252.     cons.t_state &= ~TS_BUSY;
  253.     if (cons.t_line)
  254.         (*linesw[cons.t_line].l_start)(&cons);
  255.     else
  256.         cnstart(&cons);
  257. }
  258.  
  259. cnstart(tp)
  260.     register struct tty *tp;
  261. {
  262.     register c, s;
  263.  
  264.     s = spltty();
  265.     if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
  266.         goto out;
  267.     do {
  268.     if (tp->t_outq.c_cc <= tp->t_lowat) {
  269.         if (tp->t_state&TS_ASLEEP) {
  270.             tp->t_state &= ~TS_ASLEEP;
  271.             wakeup((caddr_t)&tp->t_outq);
  272.         }
  273.         if (tp->t_wsel) {
  274.             selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
  275.             tp->t_wsel = 0;
  276.             tp->t_state &= ~TS_WCOLL;
  277.         }
  278.     }
  279.     if (tp->t_outq.c_cc == 0)
  280.         goto out;
  281.     c = getc(&tp->t_outq);
  282.     splx(s);
  283.     sput(c, conssp);
  284.     s = spltty();
  285.     } while(1);
  286. out:
  287.     splx(s);
  288. }
  289.  
  290. /*
  291.  * Kernel character output
  292.  */
  293. cnputc(c)
  294.     char c;
  295. {
  296.     if (c == '\n')
  297.         sput('\r', &sysscreen);
  298.     sput(c, &sysscreen);
  299.  
  300.     /* make the current screen visable, operator *must* know now! */
  301.     if(dispsp != &sysscreen) gotoscrn(&sysscreen);
  302. }
  303.  
  304. /*
  305.  * Set line parameters - none, but must keep kernel happy.
  306.  */
  307. cnparam(tp, t)
  308.     register struct tty *tp;
  309.     register struct termios *t;
  310. {
  311.     register int cflag = t->c_cflag;
  312.  
  313.         tp->t_ispeed = t->c_ispeed;
  314.         tp->t_ospeed = t->c_ospeed;
  315.         tp->t_cflag = cflag;
  316.  
  317.     return(0);
  318. }
  319.  
  320. /* Sync software's cursor to hardware every tenth of a second */
  321. update_cursor(sp) register struct crtscreen *sp;
  322. {     int pos = dispsp->s_cursor;
  323.  
  324.     outb(addr_6845, 14);
  325.     outb(addr_6845+1, pos>> 8);
  326.     outb(addr_6845, 15);
  327.     outb(addr_6845+1, pos);
  328.     outb(addr_6845, 10);
  329.     outb(addr_6845+1, 0);
  330.     outb(addr_6845, 11);
  331.     outb(addr_6845+1, 18);
  332.     timeout(update_cursor, sp, hz/10);
  333. }
  334.  
  335. /* Extract cursor location */
  336. get_cursor() {
  337.     unsigned cursorat;
  338.  
  339.     outb(addr_6845,14);
  340.     cursorat = inb(addr_6845+1)<<8 ;
  341.     outb(addr_6845,15);
  342.     cursorat |= inb(addr_6845+1);
  343.     return(cursorat);
  344. }
  345.  
  346. u_char shfts, ctls, alts, caps, num, stp, scroll;
  347.  
  348. /*
  349.  * Compensate for abysmally stupid frame buffer aribitration with macro
  350.  */
  351. #define    wrtchar(c, att) { \
  352.     do {    crt[cursor].c_chr = (c); \
  353.         crt[cursor].c_attr = (att); \
  354.     } while ((c) != crt[cursor].c_chr || (att) != crt[cursor].c_attr); \
  355.     cursor++; \
  356. }
  357.  
  358. /* sput has support for emulation of the 'ibmpc' termcap entry. */
  359. sput(c, sp)
  360. struct crtscreen *sp;
  361. {
  362.     register union crtbuf *crt;
  363.  
  364.     static int esc, ebrac, eparm, cx, cy, row, cursor;
  365.  
  366.     /* check if we need to initialize BEFORE autoconfiguration! */
  367.     if (dispsp == 0) {
  368.         union crtbuf *cp = Crtat + (CGA_BUF-MONO_BUF)/CHR;
  369.         u_short was;
  370.  
  371.         /* Crtat initialized to point to MONO buffer   */
  372.         /* if not present change to CGA_BUF offset     */
  373.         /* ONLY ADD the difference since locore.s adds */
  374.         /* in the remapped offset at the right time    */
  375.  
  376.         was = cp->c_wd;
  377.         cp->c_wd = 0xA55A;
  378.         if (cp->c_wd != 0xA55A) {
  379.             addr_6845 = MONO_BASE;
  380.         } else {
  381.             cp->c_wd = was;
  382.             addr_6845 = CGA_BASE;
  383.             Crtat = Crtat + (CGA_BUF-MONO_BUF)/CHR;
  384.         }
  385.  
  386.         sp = dispsp = &sysscreen;
  387.         initscrn(sp);
  388.         sp->s_cursor = get_cursor();
  389.         fill(' ', sp->s_curat, Crtat + sp->s_cursor,
  390.             COL*ROW - sp->s_cursor);
  391.     }
  392.  
  393.     /* are we the currently displaying screen or just a buffer? */
  394.     if(dispsp == sp) {
  395.         crt = Crtat;
  396.         cursor = sp->s_cursor;
  397.     } else {
  398.         crt = sp->s_buf;
  399.         cursor = sp->s_cursor;
  400.     }
  401.  
  402.     /* display a character */
  403.     switch(c) {
  404.  
  405.     case 0x1B:    /* an ESC */
  406.         esc = 1; ebrac = 0; eparm = 0;
  407.         break;
  408.  
  409.     case '\t':
  410.         cursor += (8 - cursor % 8);    /* non-destructive tab */
  411.         break;
  412.  
  413.     case '\010':
  414.         cursor--; /* non-destructive backspace */
  415.         break;
  416.  
  417.     case '\r':
  418.         cursor -= cursor % COL;
  419.         break;
  420.  
  421.     case '\n':
  422.         cursor += COL ;
  423.         break;
  424.  
  425.     default:
  426.         if (esc) {
  427.             if (ebrac) {
  428.                 switch(c) {
  429.                 case 'x': /* experimental multiple screens */
  430.                     if (cx == 0){
  431.                         sp = &toplvl;
  432.                         gotoscrn(sp);
  433.                         sp = conssp = dispsp;
  434.                     } else if (cx == 1) {
  435.                         newscrn(sp);
  436.                         sp = conssp = dispsp;
  437.                     } else if (cx == 2) {
  438.                         sp = sp->s_back;
  439.                         gotoscrn(sp);
  440.                         sp = conssp = dispsp;
  441.                     }
  442.                     if (eparm) {
  443.                         sp->s_bgat = cy;
  444.                         fillbgat(cy, crt, COL*ROW);
  445.                     }
  446.                     esc = 0; ebrac = 0; eparm = 0;
  447.                     break;
  448.                 case 'm': /* support for standout */
  449.                     if (cx == 0)sp->s_curat = sp->s_dfltat;
  450.                     else sp->s_curat = cx;
  451.                     if (eparm) sp->s_dfltat = cy;
  452.                     esc = 0; ebrac = 0; eparm = 0;
  453.                     break;
  454.                 case 'A': /* back one row */
  455.                     cursor -= COL;
  456.                     esc = 0; ebrac = 0; eparm = 0;
  457.                     break;
  458.                 case 'B': /* down one row */
  459.                     cursor += COL;
  460.                     esc = 0; ebrac = 0; eparm = 0;
  461.                     break;
  462.                 case 'C': /* right cursor */
  463.                     cursor++;
  464.                     esc = 0; ebrac = 0; eparm = 0;
  465.                     break;
  466.                 case 'J': /* Clear to end of display */
  467.                     fill(' ', sp->s_curat, crt+cursor,
  468.                         COL*ROW-cursor);
  469.                     esc = 0; ebrac = 0; eparm = 0;
  470.                     break;
  471.                 case 'K': /* Clear to EOL */
  472.                     fill(' ', sp->s_curat, crt+cursor,
  473.                         COL-cursor%COL);
  474.                     esc = 0; ebrac = 0; eparm = 0;
  475.                     break;
  476.                 case 'H': /* Cursor move */
  477.                     if (!cx||!cy)
  478.                         cursor = 0;
  479.                     else
  480.                         cursor = (cx-1)*COL+cy-1;
  481.                     esc = 0; ebrac = 0; eparm = 0;
  482.                     break;
  483.                 case ';': /* Switch params in cursor def */
  484.                     eparm = 1;
  485.                     return;
  486.                 default: /* Only numbers valid here */
  487.                     if ((c >= '0')&&(c <= '9')) {
  488.                         if (eparm) {
  489.                             cy *= 10;
  490.                             cy += c - '0';
  491.                         } else {
  492.                             cx *= 10;
  493.                             cx += c - '0';
  494.                         }
  495.                     } else {
  496.                         esc = 0; ebrac = 0; eparm = 0;
  497.                     }
  498.                     return;
  499.                 }
  500.                 break;
  501.             } else if (c == 'c') { /* Clear screen & home */
  502.                 fill(' ', sp->s_curat, crt,COL*ROW);
  503.                 cursor = 0;
  504.                 esc = 0; ebrac = 0; eparm = 0;
  505.             } else if (c == '[') { /* Start ESC [ sequence */
  506.                 ebrac = 1; cx = 0; cy = 0; eparm = 0;
  507.             } else if (c == 0x1b) { /* ESC ESC sequence */
  508.                 esc = 0;
  509.                 wrtchar(c, sp->s_curat); 
  510.             } else { /* Invalid, clear state */
  511.                  esc = 0; ebrac = 0; eparm = 0;
  512.             }
  513.         } else {
  514.             /* sound the bell? */
  515.             if (c == 7)
  516.                 /* send a 1/4 second of Concert-A (440hz) */
  517.                 speaker_tone(440, hz/4);
  518.             else
  519.                 wrtchar(c, sp->s_curat); 
  520.             break;
  521.         }
  522.     }
  523.  
  524.     /* do we need to scroll? */
  525.     if (cursor >= COL*ROW) {
  526.         bcopyb(crt+COL, crt, COL*(ROW-1)*CHR);
  527.         fill(' ', sp->s_curat, crt+COL*(ROW-1),COL) ;
  528.         cursor -= COL ;
  529.     }
  530.  
  531.     /* update cursor position in data structure */
  532.     sp->s_cursor = cursor;
  533. }
  534.  
  535. static 
  536. fill(chr,att,where,cnt) register union crtbuf *where; register cnt; {
  537.  
  538.     while (cnt--) {
  539.         where->c_attr = att;
  540.         where++->c_chr = chr;
  541.     }
  542. }
  543.  
  544. static 
  545. fillatt(att, where, cnt) register union crtbuf *where; register cnt; {
  546.  
  547.     while (cnt--)
  548.         where++->c_attr = att;
  549. }
  550.  
  551. static 
  552. fillfgat(att, where, cnt) register union crtbuf *where; register cnt; {
  553.  
  554.     while (cnt--)
  555.         where++->c_fgat = att;
  556. }
  557.  
  558. static 
  559. fillbgat(att, where, cnt) register union crtbuf *where; register cnt; {
  560.  
  561.     while (cnt--)
  562.         where++->c_bgat = att;
  563. }
  564.  
  565. /* initialize a screen */
  566. static
  567. initscrn (sp) struct crtscreen *sp; {
  568.         sp->s_cursor = 0;
  569.         sp->s_dfltat = 0x7;
  570.         sp->s_curat = 0x7;
  571.         sp->s_bgat = 0x0;
  572.         sp->s_back = sp;
  573.         fill(' ', sp->s_curat, sp->s_buf,
  574.             COL*ROW);
  575. }
  576.  
  577. /* save screen and make argument current screen */
  578. static
  579. gotoscrn(newsp) struct crtscreen *newsp; {
  580.  
  581.     /* save state of current screen to backing object */
  582.     bcopyb(Crtat, dispsp->s_buf, ROW*COL*CHR);
  583.  
  584.     /* move into place new screen */
  585.     bcopyb(newsp->s_buf, Crtat,  ROW*COL*CHR);
  586.     dispsp = newsp;
  587. }
  588.  
  589. /* save screen, allocate new one, clean it, and make it current */
  590. newscrn(sp) struct crtscreen *sp; {
  591.     struct crtscreen *newsp;
  592.     
  593.     if (sp->s_next == 0)
  594.         sp->s_next = (struct crtscreen *)
  595.             malloc (sizeof(struct crtscreen), M_DEVBUF);
  596.     newsp = sp->s_next;
  597.  
  598.     bzero ((caddr_t)newsp, sizeof(struct crtscreen));
  599.     initscrn(newsp);
  600.     newsp->s_back = sp;
  601.  
  602.     gotoscrn(newsp);
  603. }
  604.  
  605. #define    L        0x0001    /* locking function */
  606. #define    SHF        0x0002    /* keyboard shift */
  607. #define    ALT        0x0004    /* alternate shift -- alternate chars */
  608. #define    NUM        0x0008    /* numeric shift  cursors vs. numeric */
  609. #define    CTL        0x0010    /* control shift  -- allows ctl function */
  610. #define    CPS        0x0020    /* caps shift -- swaps case of letter */
  611. #define    ASCII        0x0040    /* ascii code for this key */
  612. #define    STP        0x0080    /* stop output */
  613. #define    FUNC        0x0100    /* function key */
  614. #define    SCROLL        0x0200    /* scroll lock key */
  615. #define    SYSREQ        0x0400    /* sys reqkey */
  616.  
  617. u_short action[] = {
  618. 0,     ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,        /* scan  0- 7 */
  619. ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,        /* scan  8-15 */
  620. ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,        /* scan 16-23 */
  621. ASCII, ASCII, ASCII, ASCII, ASCII,   CTL, ASCII, ASCII,        /* scan 24-31 */
  622. ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,        /* scan 32-39 */
  623. ASCII, ASCII, SHF  , ASCII, ASCII, ASCII, ASCII, ASCII,        /* scan 40-47 */
  624. ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,  SHF,  ASCII,        /* scan 48-55 */
  625.   ALT, ASCII, CPS  , FUNC , FUNC , FUNC , FUNC , FUNC ,        /* scan 56-63 */
  626. FUNC , FUNC , FUNC , FUNC , FUNC , NUM, SCROLL, ASCII,        /* scan 64-71 */
  627. ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII, ASCII,        /* scan 72-79 */
  628. ASCII, ASCII, ASCII, ASCII, SYSREQ,    0,     0,     0,        /* scan 80-87 */
  629. 0,0,0,0,0,0,0,0,
  630. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  631. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,    } ;
  632.  
  633. u_char unshift[] = {    /* no shift */
  634. 0,     033  , '1'  , '2'  , '3'  , '4'  , '5'  , '6'  ,        /* scan  0- 7 */
  635. '7'  , '8'  , '9'  , '0'  , '-'  , '='  , 0177 ,'\t'  ,        /* scan  8-15 */
  636.  
  637. 'q'  , 'w'  , 'e'  , 'r'  , 't'  , 'y'  , 'u'  , 'i'  ,        /* scan 16-23 */
  638. 'o'  , 'p'  , '['  , ']'  , '\r' , CTL  , 'a'  , 's'  ,        /* scan 24-31 */
  639.  
  640. 'd'  , 'f'  , 'g'  , 'h'  , 'j'  , 'k'  , 'l'  , ';'  ,        /* scan 32-39 */
  641. '\'' , '`'  , SHF  , '\\' , 'z'  , 'x'  , 'c'  , 'v'  ,        /* scan 40-47 */
  642.  
  643. 'b'  , 'n'  , 'm'  , ','  , '.'  , '/'  , SHF  ,   '*',        /* scan 48-55 */
  644. ALT  , ' '  , CPS,     1,     2,    3 ,     4,     5,        /* scan 56-63 */
  645.  
  646.     6,     7,     8,     9,    10, NUM, STP,   '7',        /* scan 64-71 */
  647.   '8',   '9',   '-',   '4',   '5',   '6',   '+',   '1',        /* scan 72-79 */
  648.  
  649.   '2',   '3',   '0',   '.',     0,     0,     0,     0,        /* scan 80-87 */
  650. 0,0,0,0,0,0,0,0,
  651. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  652. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,    } ;
  653.  
  654. u_char shift[] = {    /* shift shift */
  655. 0,     033  , '!'  , '@'  , '#'  , '$'  , '%'  , '^'  ,        /* scan  0- 7 */
  656. '&'  , '*'  , '('  , ')'  , '_'  , '+'  , 0177 ,'\t'  ,        /* scan  8-15 */
  657. 'Q'  , 'W'  , 'E'  , 'R'  , 'T'  , 'Y'  , 'U'  , 'I'  ,        /* scan 16-23 */
  658. 'O'  , 'P'  , '{'  , '}'  , '\r' , CTL  , 'A'  , 'S'  ,        /* scan 24-31 */
  659. 'D'  , 'F'  , 'G'  , 'H'  , 'J'  , 'K'  , 'L'  , ':'  ,        /* scan 32-39 */
  660. '"'  , '~'  , SHF  , '|'  , 'Z'  , 'X'  , 'C'  , 'V'  ,        /* scan 40-47 */
  661. 'B'  , 'N'  , 'M'  , '<'  , '>'  , '?'  , SHF  ,   '*',        /* scan 48-55 */
  662. ALT  , ' '  , CPS,     0,     0, ' '  ,     0,     0,        /* scan 56-63 */
  663.     0,     0,     0,     0,     0, NUM, STP,   '7',        /* scan 64-71 */
  664.   '8',   '9',   '-',   '4',   '5',   '6',   '+',   '1',        /* scan 72-79 */
  665.   '2',   '3',   '0',   '.',     0,     0,     0,     0,        /* scan 80-87 */
  666. 0,0,0,0,0,0,0,0,
  667. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,
  668. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,    } ;
  669.  
  670. u_char ctl[] = {    /* CTL shift */
  671. 0,     033  , '!'  , 000  , '#'  , '$'  , '%'  , 036  ,        /* scan  0- 7 */
  672. '&'  , '*'  , '('  , ')'  , 037  , '+'  , 034  ,'\177',        /* scan  8-15 */
  673. 021  , 027  , 005  , 022  , 024  , 031  , 025  , 011  ,        /* scan 16-23 */
  674. 017  , 020  , 033  , 035  , '\r' , CTL  , 001  , 023  ,        /* scan 24-31 */
  675. 004  , 006  , 007  , 010  , 012  , 013  , 014  , ';'  ,        /* scan 32-39 */
  676. '\'' , '`'  , SHF  , 034  , 032  , 030  , 003  , 026  ,        /* scan 40-47 */
  677. 002  , 016  , 015  , '<'  , '>'  , '?'  , SHF  ,   '*',        /* scan 48-55 */
  678. ALT  , ' '  , CPS,     0,     0, ' '  ,     0,     0,        /* scan 56-63 */
  679. CPS,     0,     0,     0,     0,     0,     0,     0,        /* scan 64-71 */
  680.     0,     0,     0,     0,     0,     0,     0,     0,        /* scan 72-79 */
  681.     0,     0,     0,     0,SYSREQ,     0,     0,     0,        /* scan 80-87 */
  682.     0,     0,   033, '7'  , '4'  , '1'  ,     0, NUM,        /* scan 88-95 */
  683. '8'  , '5'  , '2'  ,     0, STP, '9'  , '6'  , '3'  ,        /*scan  96-103*/
  684. '.'  ,     0, '*'  , '-'  , '+'  ,     0,     0,     0,        /*scan 104-111*/
  685. 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,    } ;
  686.  
  687. /* fiddle LED's on keyboard appropriately */
  688. update_led()
  689. {
  690.     WAITKKBDRDY;
  691.     outb(KBDATA,0xED);    /* LED Command */
  692.     WAITKKBDRDY;
  693.     outb(KBDATA,scroll | 2*num | 4*caps);
  694. }
  695.  
  696. reset_cpu() {
  697.     while(1) {
  698.         WAITKKBDRDY;
  699.         outb(KBSTAT,0xFE);    /* Reset Command */
  700.         DELAY(4000000);
  701.         WAITKKBDRDY;
  702.         outb(KBSTAT,0xFF);    /* Keyboard Reset Command */
  703.     }
  704.     /* NOTREACHED */
  705. }
  706.  
  707. /* sgetc() : get a character from the keyboard.  */
  708. int sgetc()
  709. {
  710.     u_char dt; unsigned key;
  711.  
  712. loop:
  713.     /* First see if there is something in the keyboard port */
  714.     if (inb(KBSTAT)&1) dt = inb(KBDATA);
  715.     else return (KBD_NOKEY);
  716.  
  717.     /* Check for cntl-alt-del */
  718.     if (dt == KEY_DEL && ctls && alts) doreset();
  719.  
  720.     /* Check for make/break */
  721.     if (dt & KEY_BREAK) {
  722.         /* break */
  723.         dt = dt & KEY_CODE;
  724.         switch (action[dt]) {
  725.         case SHF:    shfts = 0;
  726.                 break;
  727.         case ALT:    alts = 0;
  728.                 break;
  729.         case CTL:    ctls = 0;
  730.                 break;
  731.         case FUNC:    break;
  732.         case SYSREQ:
  733.                 gotoscrn(conssp);
  734.         }
  735.     } else {
  736.         /* make */
  737.         dt = dt & KEY_CODE;
  738.         switch (action[dt]) {
  739.         /* LOCKING KEYS */
  740.         case NUM:
  741.             num ^= 1;
  742.             update_led();
  743.             break;
  744.         case CPS:
  745.             caps ^= 1;
  746.             update_led();
  747.             break;
  748.         case SCROLL:
  749.             scroll ^= 1;
  750.             update_led();
  751.             break;
  752.         case STP:
  753.             stp ^= 1;
  754.             if(stp) goto loop;
  755.             break;
  756.  
  757.         /* NON-LOCKING KEYS */
  758.         case SHF:
  759.             shfts = 1;
  760.             break;
  761.         case ALT:
  762.             alts = 1;
  763.             break;
  764.         case CTL:
  765.             ctls = 1;
  766.             break;
  767.         case ASCII:
  768.             if (shfts) dt = shift[dt];
  769.             else if (ctls) dt = ctl[dt];
  770.             else dt = unshift[dt];
  771.             if (caps && (dt >= 'a' && dt <= 'z'))
  772.                 dt -= 'a' - 'A';
  773.             return(dt);
  774.             break;
  775.         case SYSREQ:
  776.             gotoscrn(&sysscreen);
  777.         }
  778.     }
  779.     return (KBD_NOKEY);
  780. }
  781.  '.'  , '/'  , SHF  ,   '*',        /* scan 48-55 */
  782. ALT  , ' '  , CPS,     1,     2,    3 ,     4,     5,        /* scan 56-63 */
  783.  
  784.     6,     7,     8,     9,  
  785.